package com.paic.hmily.dialog.library;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.view.View;

import java.text.DecimalFormat;

/**
 * 自定义圆圈带线条的进度控件。
 *
 * <pre class="prettyprint">
 * &#060;CustomCircleLineProgressBar
 * 	xmlns:navigation="http://schemas.android.com/apk/res-auto"
 * 	android:layout_width="wrap_content"
 * 	android:layout_height="wrap_content"
 * 	hehui:custom_circle_line_progress_bar_progress="0.2"
 * 	hehui:custom_circle_line_progress_bar_max="500"
 * 	hehui:custom_circle_line_progress_bar_line_count="120"
 * 	hehui:custom_circle_line_progress_bar_bottom_circle_start_angle="135"
 * 	hehui:custom_circle_line_progress_bar_bottom_circle_sweep_angle="270"
 * 	hehui:custom_circle_line_progress_bar_bottom_circle_color="@color/custom_circle_line_progress_bar_bottom_circle_default_background_color"
 * 	hehui:custom_circle_line_progress_bar_bottom_circle_width="@dimen/custom_circle_line_progress_bar_bottom_circle_default_width"
 * 	hehui:custom_circle_line_progress_bar_top_circle_color="@color/custom_circle_line_progress_bar_top_circle_default_background_color"
 * 	hehui:custom_circle_line_progress_bar_top_circle_width="@dimen/custom_circle_line_progress_bar_top_circle_default_width"
 * 	hehui:custom_circle_line_progress_bar_top_circle_both_sides_long_line_color="@color/custom_circle_line_progress_bar_top_circle_both_sides_long_line_default_background_color"
 * 	hehui:custom_circle_line_progress_bar_top_circle_inner_short_line_reached_color="@color/custom_circle_line_progress_bar_top_circle_inner_short_line_reached_default_background_color"
 * 	hehui:custom_circle_line_progress_bar_top_circle_inner_short_line_unreached_color="@color/custom_circle_line_progress_bar_top_circle_inner_short_line_unreached_default_background_color"
 * 	hehui:custom_circle_line_progress_bar_center_text_size="@dimen/custom_circle_line_progress_bar_center_text_default_size"
 * 	hehui:custom_circle_line_progress_bar_center_text_color="@color/custom_circle_line_progress_bar_center_text_default_text_color"
 * 	hehui:custom_circle_line_progress_bar_center_text_visible="visible"
 * 	hehui:custom_circle_line_progress_bar_center_text_show_style="number"
 * 	hehui:custom_circle_line_progress_bar_little_point_size="@dimen/"custom_circle_line_progress_bar_little_point_default_size""
 * 	hehui:custom_circle_line_progress_bar_little_point_background_color="@color/custom_circle_line_progress_bar_little_point_default_background_color"&#047;&#062;
 * </pre>
 *
 * @author hehui
 *
 */
public class CustomCircleLineProgressBar extends View {

    private int mDefaultWidthSize;
    private int mDefaultHeightSize;
    private static final String DEFAULT_PERCENT_FORMAT = "00";
    private static final String DEFAULT_NUMBER_FORMAT = "00";
    private RectF mArcRect = new RectF();

    private Paint mBottomCirclePaint;
    private Paint mTopCirclePaint;
    private Paint mTopCircleBothSidesLongLinePaint;
    private Paint mTopCircleInnerShortLineReachedPaint;
    private Paint mTopCircleInnerShortLineUnReachedPaint;
    private Paint mCenterTextPaint;
    private Paint mOutterTextPaint;
    private Paint mInnerPointPaint;

    private int mBottomCircleLineColor;
    private float mBottomCircleLineWidth;
    private int mTopCircleLineColor;
    private float mTopCircleLineWidth;
    private int mTopCircleBothSidesLongLineColor;
    private int mTopCircleInnerShortLineReachedColor;
    private int mTopCircleInnerShortLineUnReachedColor;
    private int mCenterTextSize;
    private int mCenterTextColor;
    private boolean mIsCenterTextVisible;
    private int mCenterTextType;
    private int mInnerLittlePointSize;
    private int mInnerLittlePointColor;

    private float mStartAngle;
    private float mBottomCircleLineSweepAngle;
    private float mSweepAngle;
    private float mIntervalAngle;
    /**
     * 进度值（0.0~1.0）
     */
    private float mProgress;
    private int mMax;
    private int mBottomCircleLineCount;
    private Matrix mRotateMatrix;

    private float mDiameter;
    private float mCenterX;
    private float mCenterY;
    private String mDrawTextContent = "0";
    private DecimalFormat mDecimalFormat;

    public CustomCircleLineProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);

        initTypedArray(context, attrs);

        init();
    }

    private void initTypedArray(Context context, AttributeSet attrs) {
        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.custom_circle_line_progress_bar_style);

        mProgress = array.getFloat(
                R.styleable.custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_progress, 0);
        mMax = array.getInteger(R.styleable.custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_max,
                100);
        mBottomCircleLineCount = array.getInteger(
                R.styleable.custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_line_count, 60);
        mStartAngle = Float
                .parseFloat(array
                        .getString(R.styleable
                                .custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_bottom_circle_start_angle));
        mBottomCircleLineSweepAngle = Float
                .parseFloat(array
                        .getString(R.styleable
                                .custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_bottom_circle_sweep_angle));
        if (mBottomCircleLineSweepAngle < 0 || mBottomCircleLineSweepAngle > 360) {
            throw new IllegalArgumentException(
                    "mBottomCircleSweepAngle must be in 0 to 360, mBottomCircleLineSweepAngle: "
                            + mBottomCircleLineSweepAngle);
        }

        mBottomCircleLineColor = array.getColor(
                R.styleable.custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_bottom_circle_color,
                getResources().getColor(R.color
                        .custom_circle_line_progress_bar_bottom_circle_default_background_color));
        mBottomCircleLineWidth = array.getDimension(
                R.styleable.custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_bottom_circle_width,
                getResources().getDimension(R.dimen.custom_circle_line_progress_bar_bottom_circle_default_width));

        mTopCircleLineColor = array.getColor(
                R.styleable.custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_top_circle_color,
                getResources().getColor(R.color.custom_circle_line_progress_bar_top_circle_default_background_color));
        mTopCircleLineWidth = array.getDimension(
                R.styleable.custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_top_circle_width,
                getResources().getDimension(R.dimen.custom_circle_line_progress_bar_top_circle_default_width));

        mTopCircleBothSidesLongLineColor = array
                .getColor(
                        R.styleable
                                .custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_top_circle_both_sides_long_line_color,
                        getResources().getColor(R.color
                                .custom_circle_line_progress_bar_top_circle_both_sides_long_line_default_background_color));
        mTopCircleInnerShortLineReachedColor = array
                .getColor(
                        R.styleable
                                .custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_top_circle_inner_short_line_reached_color,
                        getResources()
                                .getColor(
                                        R.color.custom_circle_line_progress_bar_top_circle_inner_short_line_reached_default_background_color));
        mTopCircleInnerShortLineUnReachedColor = array
                .getColor(
                        R.styleable
                                .custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_top_circle_inner_short_line_unreached_color,
                        getResources()
                                .getColor(
                                        R.color.custom_circle_line_progress_bar_top_circle_inner_short_line_unreached_default_background_color));
        mCenterTextSize = array.getDimensionPixelSize(
                R.styleable.custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_center_text_size,
                getResources().getDimensionPixelSize(R.dimen.custom_circle_line_progress_bar_center_text_default_size));
        mCenterTextColor = array.getColor(
                R.styleable.custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_center_text_color,
                getResources().getColor(R.color.custom_circle_line_progress_bar_center_text_default_text_color));
        mIsCenterTextVisible = array.getInt(
                R.styleable.custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_center_text_visible,
                1) == 0;
        mCenterTextType = array.getInt(R.styleable.custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_center_text_show_style, 1);

        mInnerLittlePointColor = array
                .getColor(
                        R.styleable
                                .custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_little_point_background_color,
                        getResources().getColor(
                                R.color.custom_circle_line_progress_bar_little_point_default_background_color));
        mInnerLittlePointSize = array
                .getDimensionPixelSize(
                        R.styleable
                                .custom_circle_line_progress_bar_style_custom_circle_line_progress_bar_little_point_size,
                        getResources().getDimensionPixelSize(
                                R.dimen.custom_circle_line_progress_bar_little_point_default_size));

        array.recycle();
    }

    private void init() {
        mDefaultWidthSize = DimensConvert.dip2px(getContext(), 20);
        mDefaultHeightSize = DimensConvert.dip2px(getContext(), 20);
        mRotateMatrix = new Matrix();

        // number、percent、custom
        if (mCenterTextType == 0) {
            mDecimalFormat = new DecimalFormat(DEFAULT_NUMBER_FORMAT);
        } else if (mCenterTextType == 1) {
            mDecimalFormat = new DecimalFormat(DEFAULT_PERCENT_FORMAT);
        }

        mBottomCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBottomCirclePaint.setColor(mBottomCircleLineColor);
        mBottomCirclePaint.setStrokeWidth(mBottomCircleLineWidth);
        mBottomCirclePaint.setStyle(Style.STROKE);

        mTopCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTopCirclePaint.setColor(mTopCircleLineColor);
        mTopCirclePaint.setStrokeWidth(mTopCircleLineWidth);
        mTopCirclePaint.setStyle(Style.STROKE);

        mTopCircleBothSidesLongLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTopCircleBothSidesLongLinePaint.setColor(mTopCircleBothSidesLongLineColor);
        mTopCircleBothSidesLongLinePaint.setStrokeWidth(2);

        mTopCircleInnerShortLineReachedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTopCircleInnerShortLineReachedPaint.setColor(mTopCircleInnerShortLineReachedColor);
        mTopCircleInnerShortLineReachedPaint.setStrokeWidth(2);

        mTopCircleInnerShortLineUnReachedPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mTopCircleInnerShortLineUnReachedPaint.setColor(mTopCircleInnerShortLineUnReachedColor);
        mTopCircleInnerShortLineUnReachedPaint.setStrokeWidth(2);

        mCenterTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mCenterTextPaint.setColor(mCenterTextColor);
        mCenterTextPaint.setTextSize(mCenterTextSize);
        mCenterTextPaint.setTypeface(Typeface.DEFAULT_BOLD);

        mOutterTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mOutterTextPaint.setColor(mCenterTextColor);
        mOutterTextPaint.setTextSize(mCenterTextSize / 2);

        mInnerPointPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mInnerPointPaint.setColor(mInnerLittlePointColor);
        mInnerPointPaint.setStyle(Style.FILL);
        mInnerPointPaint.setStrokeWidth(mInnerLittlePointSize);

        mIntervalAngle = mBottomCircleLineSweepAngle * 1.0f / mBottomCircleLineCount;
        calcProgressInner(mProgress);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        drawBottomCircleInner(canvas);

        drawTopCircleInner(canvas);

        // drawTopLineInner(canvas);

        drawTextInner(canvas);

        // drawBothSidesTextInner(canvas);

        // drawPointInner(canvas);
    }

    private void drawBottomCircleInner(Canvas canvas) {
        canvas.drawArc(mArcRect, mStartAngle, mBottomCircleLineSweepAngle, false, mBottomCirclePaint);
    }

    private void drawTopCircleInner(Canvas canvas) {
        canvas.drawArc(mArcRect, mStartAngle, mSweepAngle, false, mTopCirclePaint);
    }

    private void drawTopLineInner(Canvas canvas) {
        float destAngle = mStartAngle + mBottomCircleLineSweepAngle;
        float passedAngle = mStartAngle + mSweepAngle;

        mRotateMatrix.reset();
        for (float i = mStartAngle; i <= destAngle; i += mIntervalAngle) {
            mRotateMatrix.postRotate(i, mCenterX, mCenterY);
            canvas.save();
            canvas.concat(mRotateMatrix);

            if (i == mStartAngle || i >= destAngle) {
                canvas.drawLine(mCenterX + mDiameter / 2 - mBottomCircleLineWidth / 2, mCenterY, mCenterX + mDiameter
                        / 2 + mBottomCircleLineWidth * 3 / 4, mCenterY, mTopCircleBothSidesLongLinePaint);
            } else {
                if (i <= passedAngle) {
                    canvas.drawLine(mCenterX + mDiameter / 2 - mBottomCircleLineWidth / 2, mCenterY, mCenterX
                                    + mDiameter / 2 + mBottomCircleLineWidth / 2, mCenterY,
                            mTopCircleInnerShortLineReachedPaint);
                } else {
                    canvas.drawLine(mCenterX + mDiameter / 2 - mBottomCircleLineWidth / 2, mCenterY, mCenterX
                                    + mDiameter / 2 + mBottomCircleLineWidth / 2, mCenterY,
                            mTopCircleInnerShortLineUnReachedPaint);
                }
            }

            canvas.restore();
            mRotateMatrix.reset();
        }
    }

    private void drawTextInner(Canvas canvas) {
        if (mIsCenterTextVisible) {
            // number、percent、custom
            if (mCenterTextType == 0) {
                mDrawTextContent = mDecimalFormat.format(mProgress * mMax);
            } else if(mCenterTextType == 1){
                mDrawTextContent = mDecimalFormat.format(mProgress * 100) + "%";
            }

            float textWidth = mCenterTextPaint.measureText(mDrawTextContent);
            float textStartPosition = mCenterX - textWidth / 2;

            float textEndPosition = (int) (mCenterY - ((mCenterTextPaint.descent() + mCenterTextPaint.ascent()) / 2.0f));
            canvas.drawText(mDrawTextContent, textStartPosition, textEndPosition, mCenterTextPaint);
        }
    }

    private void drawBothSidesTextInner(Canvas canvas) {
        float tempRadius = mDiameter / 2 + mBottomCircleLineWidth * 1.5f;
        float leftStartX = mCenterX + (float) Math.cos(Math.toRadians(mStartAngle)) * tempRadius;
        float leftStartY = mCenterY + (float) Math.sin(Math.toRadians(mStartAngle)) * tempRadius;

        float rightStartX = mCenterX + (float) Math.cos(Math.toRadians(mStartAngle + mBottomCircleLineSweepAngle))
                * tempRadius;
        float rightStartY = mCenterY + (float) Math.sin(Math.toRadians(mStartAngle + mBottomCircleLineSweepAngle))
                * tempRadius;

        String leftContent = "000";
        String rightContent = String.valueOf(mMax);

        canvas.drawText(leftContent, leftStartX - mOutterTextPaint.measureText(leftContent) / 2,
                ((int) (leftStartY - ((mOutterTextPaint.descent() + mOutterTextPaint.ascent()) / 2.0f))),
                mOutterTextPaint);

        canvas.drawText(rightContent, rightStartX - mOutterTextPaint.measureText(rightContent) / 2,
                ((int) (rightStartY - ((mOutterTextPaint.descent() + mOutterTextPaint.ascent()) / 2.0f))),
                mOutterTextPaint);
    }

    private void drawPointInner(Canvas canvas) {
        float pointStartX = mCenterX + mDiameter / 2 - mBottomCircleLineWidth / 2 - mInnerLittlePointSize;

        mRotateMatrix.reset();
        mRotateMatrix.postRotate(mStartAngle + mSweepAngle, mCenterX, mCenterY);
        canvas.save();

        canvas.concat(mRotateMatrix);
        canvas.drawCircle(pointStartX, mCenterY, mInnerLittlePointSize / 2, mInnerPointPaint);

        canvas.restore();
        mRotateMatrix.reset();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);

        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);

        int desireWidth = mDefaultWidthSize;
        int desireHeight = mDefaultHeightSize;

        if (widthMode == MeasureSpec.EXACTLY) {
            desireWidth = widthSize;
        } else if (widthMode == MeasureSpec.AT_MOST) {
            desireWidth = Math.min(mDefaultWidthSize, widthSize);
        }

        if (heightMode == MeasureSpec.EXACTLY) {
            desireHeight = heightSize;
        } else if (heightMode == MeasureSpec.AT_MOST) {
            desireHeight = Math.min(mDefaultHeightSize, widthSize);
        }

        int remainHeight = desireHeight - getPaddingTop() - getPaddingBottom();
        int remainWidth = desireWidth - getPaddingLeft() - getPaddingRight();
        mDiameter = remainHeight > remainWidth ? remainWidth : remainHeight;

        // 再缩短一下直径来容纳底部两端的文字
        mDiameter = mDiameter * 5 / 6;

        float left = getPaddingLeft() + remainWidth / 2 - mDiameter / 2;
        float top = getPaddingTop() + remainHeight / 2 - mDiameter / 2;
        float right = left + mDiameter;
        float bottom = top + mDiameter;
        mArcRect.set(left, top, right, bottom);

        mCenterX = left + mDiameter / 2;
        mCenterY = top + mDiameter / 2;

        setMeasuredDimension(desireWidth, desireHeight);
    }

    public synchronized float getProgress() {
        return mProgress;
    }

    public synchronized void setProgress(float progress) {
        if (mProgress >= 1.0f) {
            return;
        }

        calcProgressInner(progress);

        postInvalidate();
    }

    /**
     * 设置文本显示的内容。
     *
     * @param drawTextContent
     */
    public void setDrawTextContent(String drawTextContent) {
        mDrawTextContent = drawTextContent;

        postInvalidate();
    }

    private void calcProgressInner(float progress) {
        if (progress < 0) {
            mProgress = 0;
        } else if (progress > 1.0f) {
            mProgress = 1.0f;
        } else {
            mProgress = progress;
        }

        mSweepAngle = mProgress * mBottomCircleLineSweepAngle;
        if (mSweepAngle > 360) {
            mSweepAngle = 360;
        } else if (mSweepAngle < 0) {
            mSweepAngle = 0;
        }
    }

    public void reset() {
        mSweepAngle = 0;
        mProgress = 0;
        mRotateMatrix.reset();
    }
}
